package com.lobstar.xrpc.server.handler;

import java.lang.reflect.InvocationTargetException;

import com.lobstar.xrpc.common.handler.ServiceHandler;
import com.lobstar.xrpc.common.po.SMessage;
import com.lobstar.xrpc.common.po.SMessage.Type;
import com.lobstar.xrpc.server.main.MainServer;
import com.lobstar.xrpc.service.base.ServiceInvoker;
import com.lobstar.xrpc.service.utils.JsonUtils;

import io.netty.channel.ChannelHandlerContext;

public class ServerHandler extends ServiceHandler {

	protected MainServer holder;

	public ServerHandler(MainServer server) {
		super(server);
		this.holder = server;
	}

	private String id;

	@Override
	protected void handleHeartbeat(ChannelHandlerContext ctx, SMessage msg) {
		if(msg.getType() == Type.HEART) {
			id = msg.getId();
			if(!holder.getOnlineMap().containsKey(id)) {
				holder.getGroup().add(ctx.channel());
				holder.getOnlineMap().put(id,ctx.channel());
				LOGGER.info("cabinet {} linked,now online cabinets num: {}",id,holder.getOnlineMap().size());
			}
		}
	}
	@Override
	protected void handleInit(ChannelHandlerContext ctx, SMessage msg) {
		if(msg.getType() == Type.INIT) {
			id = msg.getId();
			if(!holder.getOnlineMap().containsKey(id)) {
				holder.getGroup().add(ctx.channel());
				holder.getOnlineMap().put(id,ctx.channel());
				LOGGER.info("cabinet {} linked,now online cabinets num: {}",id,holder.getOnlineMap().size());
			}
			try {
				holder.getListeners().getOnlineListener().handle(id);
			}catch(Exception e) {
				ctx.disconnect();
			}
		}
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		holder.getOnlineMap().remove(id);
		LOGGER.info("cabinet {} is offline!",id);
		holder.getListeners().getOfflineListener().handle(id);
		super.channelInactive(ctx);
	}

	@Override
	protected void handleRequest(ChannelHandlerContext ctx, SMessage msg) {
		System.out.println(System.currentTimeMillis()+",request--->"+msg);
		holder.getTaskProcessor().execute(()->{
			Object ret = null;
			Object ex = null;
			ServiceInvoker invoker = holder.getInvoker();
			//记录msg的id标识返回对象
			try {
				if(invoker.hasMethod(msg)) {
					try {
						ret = invoker.invoke(msg);
						msg.addAttribute(TAG_RESPONSE, JsonUtils.toJson(ret));
					}catch(Exception e) {
						if(e.getClass() == InvocationTargetException.class) {
							ex = ((InvocationTargetException)e).getTargetException().toString();
						}else {
							ex = e.toString();
						}
					}
				}else {
					ex = "no method";
				}
				if(ex != null) {
					msg.addAttribute(TAG_EXCEPTION, ex);
				}
				ctx.channel().writeAndFlush(msg.buildResponse());
			}catch(Exception e) {
				LOGGER.error("request",e);
				throw e;
			}
		});
	}
}
